/*
Copyright 2024 - 2025 Zen HuiFer

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package router

import (
	"context"
	"encoding/json"
	"fmt"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/google/uuid"
	"igp/biz"
	"igp/glob"
	"igp/models"
	"igp/servlet"
	"igp/ut"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type MqttApi struct{}

var bizMqtt = biz.MqttClientBiz{}
var nodeBiz = biz.NodeBiz{}
var scriptBiz = biz.ScriptBiz{}

// CreateMqtt
// @Tags      MQTT
// @Summary   创建MQTT客户端
// @accept    application/json
// @Produce   application/json
// @Param     data  body      models.MqttClient true "创建参数"
// @Success   200  {object}  servlet.JSONResult{data=models.MqttClient}
// @Router    /mqtt/create [post]
func (s *MqttApi) CreateMqtt(c *gin.Context) {
	mqttClient := models.MqttClient{}
	err := c.ShouldBind(&mqttClient)
	if err != nil {
		glob.GLog.Sugar().Error("操作异常", err)
		panic(err)
	}
	mqtt := bizMqtt.CreateMqtt(mqttClient)
	name := ut.CalcBucketName(glob.GConfig.InfluxConfig.Bucket, "MQTT", mqtt.ID)
	ut.CheckBucketNameAndCreate(name)
	servlet.Resp(c, mqtt)
}

// UpdateMqtt
// @Tags      MQTT
// @Summary   修改MQTT客户端
// @accept    application/json
// @Produce   application/json
// @Param     data  body      models.MqttClient true "创建参数"
// @Success   200  {object}  servlet.JSONResult{data=models.MqttClient}
// @Router    /mqtt/update [post]
func (s *MqttApi) UpdateMqtt(c *gin.Context) {
	var req models.MqttClient

	if err := c.ShouldBindJSON(&req); err != nil {
		servlet.Error(c, err.Error())

		return
	}
	var old models.MqttClient

	result := glob.GDb.First(&old, req.ID)
	if result.Error != nil {
		servlet.Error(c, "MQTT_CLIENT not found")
		return
	}
	var newV models.MqttClient
	newV = old
	newV.Subtopic = req.Subtopic
	newV.Username = req.Username
	newV.Password = req.Password
	newV.Host = req.Host
	newV.Port = req.Port
	// 更新记录
	result = glob.GDb.Model(&newV).Updates(newV)
	if result.Error != nil {
		servlet.Error(c, result.Error.Error())

		return
	}
	servlet.Resp(c, old)
}

// StartMqtt
// @Tags      MQTT
// @Summary   启动MQTT客户端
// @Produce   application/json
// @Param id query string false "mqtt_client表id"
// @Router    /mqtt/start [get]
// @Success 200 {object}  servlet.JSONResult{data=string}
func (s *MqttApi) StartMqtt(c *gin.Context) {
	var id = c.Query("id")

	start := bizMqtt.Start(id)
	param := nodeBiz.SendCreateParam(start)
	glob.GLog.Sugar().Info(param)

	var m map[string]interface{}
	err := json.Unmarshal([]byte(param), &m)
	if err != nil {
		zap.S().Error("Error unmarshalling JSON", zap.Error(err))
		// 这里可以返回错误或者处理错误
		servlet.Error(c, "JSON 解析异常")
		return
	}
	msg := m["message"]

	servlet.Resp2(c, fmt.Sprintf("%v", msg))

}

// StopMqtt
// @Tags      MQTT
// @Summary   停止MQTT客户端
// @Produce   application/json
// @Param id query string false "mqtt_client表id"
// @Router    /mqtt/stop [get]
// @Success 200 {object}  servlet.JSONResult{data=string}
func (s *MqttApi) StopMqtt(c *gin.Context) {
	var id = c.Query("id")

	start := bizMqtt.Start(id)
	param := nodeBiz.SendStopParam(start)
	glob.GLog.Sugar().Info(param)

	var m map[string]interface{}
	err := json.Unmarshal([]byte(param), &m)
	if err != nil {
		zap.S().Error("Error unmarshalling JSON", zap.Error(err))
		// 这里可以返回错误或者处理错误
		return
	}
	glob.GLog.Sugar().Info(param)

	msg := m["message"]

	servlet.Resp2(c, fmt.Sprintf("%v", msg))

}

// SendMqttMessage
// @Tags      MQTT
// @Summary   发送MQTT消息
// @Produce   application/json
// @Param id query string false "客户端ID"
// @Param     data  body      servlet.ParamStruct true "消息"
// @Router    /mqtt/send [post]
// @Success 200 {object}  servlet.JSONResult{data=string}
func (s *MqttApi) SendMqttMessage(c *gin.Context) {
	var id = c.Query("id")
	requestBody, err := c.GetRawData()
	if err != nil {
		servlet.Error(c, err.Error())
		return
	}

	type paramStruct struct {
		Topic    string `json:"topic"`
		QOS      byte   `json:"qos"`
		Retained bool   `json:"retained"`
		Payload  string `json:"payload"`
	}
	var params paramStruct

	err = json.Unmarshal([]byte(requestBody), &params)


	byId, err := bizMqtt.FindByClientId(id)

	if err != nil {
		servlet.Error(c, err.Error())
		return
	}
	connect := MqttConnect(byId.Host, byId.Password, byId.Password, byId.Port,"send+"+uuid.New().String())
	if connect != nil {

	connect.Publish(params.Topic,params.QOS,params.Retained,params.Payload)
	connect.Disconnect(10)

	}


	servlet.Resp2(c, fmt.Sprintf("%v", "发送成功"))

}


func  MqttConnect(host, username, password string, port int,id string) mqtt.Client {
	opts := mqtt.NewClientOptions()
	opts.AddBroker(fmt.Sprintf("tcp://%s:%d", host, port))
	opts.SetUsername(username)
	opts.SetAutoReconnect(false)
	opts.SetPassword(password)
	opts.SetClientID(id)
	opts.OnConnectionLost = func(client mqtt.Client, err error) {
		zap.S().Errorf("mqtt connection lost id = %s , error = %+v", id, err)
	}

	opts.SetOrderMatters(false)
	opts.SetKeepAlive(60 * time.Second)
	// 创建并启动客户端
	client := mqtt.NewClient(opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		return nil
	}

	return client
}


// PageMqtt
// @Tags      MQTT
// @Summary   分页查询MQTT客户端
// @Produce   application/json
// @Param client_id query string false "客户端名称" maxlength(100)
// @Param page query int false "页码"
// @Param page_size query int false "每页数量"
// @Success   200  {object} servlet.JSONResult{data=servlet.PaginationQ{data=models.MqttClient}}
// @Router    /mqtt/page [get]
func (s *MqttApi) PageMqtt(c *gin.Context) {

	var name = c.Query("client_id")
	var page = c.DefaultQuery("page", "0")
	var pageSize = c.DefaultQuery("page_size", "10")
	parseUint, err := strconv.Atoi(page)
	if err != nil {
		servlet.Error(c, "无效的页码")
		return
	}
	u, err := strconv.Atoi(pageSize)

	if err != nil {
		servlet.Error(c, "无效的页长")

		return
	}

	data, err := bizMqtt.PageMqttData(name, parseUint, u)
	if err != nil {
		servlet.Error(c, "查询异常")

		return
	}
	servlet.Resp(c, data)
}

// NodeUsingStatus
// @Tags      MQTT
// @Summary   查询节点使用情况
// @Produce   application/json
// @Router    /mqtt/node-using-status [get]
// @Success 200 {object}  servlet.JSONResult{data=string}
func (s *MqttApi) NodeUsingStatus(c *gin.Context) {

	status := nodeBiz.SendNodeUsingStatus()

	glob.GLog.Sugar().Info(status)

	servlet.Resp(c, status)

}

// DeleteMqtt
// @Tags      MQTT
// @Summary   删除MQTT客户端
// @Param id path int true "主键"
// @Produce   application/json
// @Router    /mqtt/delete/:id [post]
// @Success 200 {object}  servlet.JSONResult{data=string}
func (s *MqttApi) DeleteMqtt(c *gin.Context) {
	var mqttClient models.MqttClient

	param := c.Param("id")

	result := glob.GDb.First(&mqttClient, param)
	if result.Error != nil {
		servlet.Error(c, "MQTT_CLIENT not found")
		return
	}

	if result := glob.GDb.Delete(&mqttClient); result.Error != nil {
		servlet.Error(c, result.Error.Error())
		return
	}

	glob.GRedis.HDel(context.Background(), "mqtt_script", param)

	servlet.Resp(c, "删除成功")
}

// SetScript
// @Tags      MQTT
// @Summary   设置解析脚本
// @accept    application/json
// @Param     data  body      servlet.MqttScript true "创建参数"
// @Produce   application/json
// @Router    /mqtt/set-script [post]
// @Success 200 {object}  servlet.JSONResult{data=string}
func (s *MqttApi) SetScript(c *gin.Context) {

	var scriptData servlet.MqttScript

	if err := c.BindJSON(&scriptData); err != nil {
		servlet.Error(c, "Invalid request body")
		return
	}

	var mqttClient models.MqttClient
	result := glob.GDb.First(&mqttClient, scriptData.ID)

	if result.Error != nil {
		servlet.Error(c, "MQTT_CLIENT not found")
		return
	}

	mqttClient.Script = scriptData.Script

	result = glob.GDb.Model(&mqttClient).Updates(mqttClient)

	if result.Error != nil {
		servlet.Error(c, "Failed to update script")

		return
	}
	bizMqtt.SetScriptRedis(mqttClient.ClientId, mqttClient.Script)
	servlet.Resp(c, "ok")

}

// CheckScript
// @Tags      MQTT
// @Summary   设置解析脚本
// @accept    application/json
// @Param     data  body      servlet.CheckScriptReq true "创建参数"
// @Produce   application/json
// @Router    /mqtt/check-script [post]
// @Success 200 {object}  servlet.JSONResult{data=string}
func (s *MqttApi) CheckScript(c *gin.Context) {
	var req servlet.CheckScriptReq
	if err := c.BindJSON(&req); err != nil {
		servlet.Error(c, err.Error())
		return
	}

	result := scriptBiz.CheckScript(req.Param, req.Script)
	if result == nil {
		servlet.Error(c, "执行脚本失败")
		return
	} else {
		servlet.Resp(c, result)
		return
	}

}

// ListMqtt
// @Summary  MQTT客户端列表
// @Description MQTT客户端列表
// @Tags MQTT
// @Accept json
// @Produce json
// @Success 200 {object} servlet.JSONResult{data=models.MqttClient[]}
// @Failure 400 {string} string "请求参数错误"
// @Failure 500 {string} string "查询异常"
// @Router /mqtt/list [get]
func (s *MqttApi) ListMqtt(c *gin.Context) {

	var list []models.MqttClient
	glob.GDb.Find(&list)
	servlet.Resp(c, list)

}

// ByIdMqtt
// @Summary  MQTT单个详情
// @Description MQTT单个详情
// @Tags MQTT
// @Accept json
// @Produce json
// @Success 200 {object} servlet.JSONResult{data=models.MqttClient}
// @Failure 400 {string} string "请求参数错误"
// @Failure 500 {string} string "查询异常"
// @Router /mqtt/byId/:id [get]
func (s *MqttApi) ByIdMqtt(c *gin.Context) {
	var mqttClient models.MqttClient

	id := c.Param("id")

	result := glob.GDb.First(&mqttClient, id)
	if result.Error != nil {
		servlet.Error(c, "MqttClient not found")

		return
	}

	servlet.Resp(c, mqttClient)
}
